<?php
define('TAB_PREF',"cms_");

/**
 * В нем реализован один основной метод вызываемый через сеттер, с помощью которого подгружаются дополнительные классы. 
 */

class MF_Main 
{	
	/**
	 * Содержит строку с указанеим путя до директории с API
	 *
	 */
	private $_api_path;
	
	
	public $_config;
	
	/**
	 * Содержит ссылки на загруженные классы
	 *
	 * @var array($className => object)
	 */
	private $loadedClasses = array();
	
	
	/**
	 * Возвращает ссылку на класс Menu
	 *
	 * @var Menu
	 */
	public $Menu;
	
	/**
	 * Возвращает ссылку на класс Utils
	 *
	 * @var Utils
	 */
	public $Utils;
	
	/**
	 * Возвращяет ссылку на гласс _sql
	 *
	 * @var _sql
	 */
	public $_sql;
	
	/**
	 * Возвращяет ссылку на singlton класса Page
	 *
	 * @var Page
	 */
	public $Page;
	
	/**
	 * Возвращает ссылку на класс Html
	 *
	 * @var Html
	 */
	public $Html;
	
	/**
	 * Возвращает ссылку на класс Html
	 *
	 * @var PlainText
	 */
	public $PlainText;
	
	/**
	 * Возвращяет ссылку на singlton класса Template
	 *
	 * @var Template
	 */
	public $Template;
	
	
	/**
	 * Возвращяет ссылку на singlton класса Placeholder
	 *
	 * @var Placeholder
	 */
	public $Placeholder;
	
	/**
	 * Возвращяет ссылку на singlton класса Geo
	 *
	 * @var Geo
	 */
	public $Geo;
	/**
	 * Возвращяет указатель на класс News
	 *
	 * @var News
	 */
	public $News;
	/**
	 * Возвращяет указатель на класс NewsNote
	 *
	 * @var NewsNote
	 */
	public $NewsNote;
	
	/**
	 * Returns poiner to the instance of Gallery class 
	 *
	 * @var Gallery
	 */
	public $Gallery;
	
	/**
	 * Returns poiner to the instance of Cover class 
	 *
	 * @var Cover
	 */
	public $Cover;
	/**
	 * Returns poiner to the instance of BannerList class 
	 *
	 * @var BannerList
	 */
	public $BannerList;
	
	/**
	 * Returns poiner to the instance of Catalog class
	 *
	 * @var Catalog
	 */
	public $Catalog;
	/**
	 * Returns poiner to the instance of Comments class
	 *
	 * @var Comments
	 */
	public $Comments;
	
	/**
	 * Returns poiner to the instance of FormSender class  
	 *
	 * @var FormSender
	 */
	public $FormSender;
	/**
	 * Returns poiner to the instance of Rating class
	 *
	 * @var Rating
	 */
	public $Rating;
	
	/**
	 * Returns poiner to the instance of UserList class
	 *
	 * @var UserList
	 */
	public $UserList;
	
	/*&
	 * Returns pointer to the instance of OrderList class
	 * 
	 * @var OrderList
	 */
	public $OrderList;
	
	/**
	 * Returns pointer to the instance of Administrator class
	 * 
	 * @var Administrator
	 */
	public $Administrator;
	
	/**
	 * Returns pointer to the instance of AdminGroup class
	 *
	 * @var AdminGroup
	 */
	public $AdminGroup;
	
	/**
	 * Returns pointer to the instance of CmsModule class
	 *
	 * @var CmsModule
	 */
	public $CmsModule;
	/**
	 * Pointer to self
	 *
	 * @var self
	 */
	private static $_instance;
	
	/**
	 * Return current object instance
	 * @var $config Zend_Config_Ini|String
	 * @return MF_Main
	 */
	public static function getInstance($config = null)
    {
        if (null === self::$_instance) {
            self::$_instance = new self($config);
        }

        return self::$_instance;
    }
	
	
/*	public function __construct($xml_tuning = "") {
		if ($xml_tuning!="") {
			$xmlDoc = $this->Utils->ParseXML($xml_tuning);
			$paramNodes = $xmlDoc->getElementsByTagName("flag");
			if ($paramNodes!=null) {
				$paramNodesLen = $paramNodes->getLength();
				for ($p=0;$p<$paramNodesLen;$p++) {
					$paramNode = $paramNodes->item($p);
					define($paramNode->getAttribute('key'), $paramNode->getAttribute('value'));
				}
			}
		}
	}*/
	
    
	public function __construct($config = null) {
		unset($this->Menu);
		unset($this->Utils);
		unset($this->_sql);
		unset($this->Page);
		unset($this->Html);
		unset($this->PlainText);
		unset($this->Template);
		unset($this->Placeholder);
		unset($this->Geo);
		unset($this->News);
		unset($this->NewsNote);
		unset($this->Gallery);
		unset($this->Cover);
		unset($this->BannerList);
		unset($this->Catalog);
		unset($this->Comments);
		unset($this->Rating);
		unset($this->UserList);
		unset($this->FormSender);
		unset($this->OrderList);
		unset($this->Administrator);
		unset($this->AdminGroup);
		unset($this->CmsModule);
		
		if (gettype($config)=="string") {
			$this->_config = new Zend_Config_Ini($config);
		}
		
		// TODO сделать установку TAB_PREF из ини файла
		// $this->_tab_pref =  ...;
		// define('TAB_PREF', ...);
		
		// TODO сделать проверку. если установлен api path в ini файле, тогда определять от туда
		$this->setApiPath(realpath(dirname(__FILE__)));
	}
	
	
	/**
	 * По имени переменной $var проверяет загружен ли такой класс уже и есть ли на него ссылка 
	 * в свойстве  $loadedClasses, иначе загружает его в память с помощью метода loadClass и создает ссылку. 
	 * Возвращает ссылку на класс, либо false в случае его не существования.
	 *
	 * @param string $var
	 * @return mixed
	 */
	public function __get($var)
	{
		if ($var=="api_path") { 
			return $this->_api_path;
		} elseif (!isset($this->loadedClasses[$var])) { 
			$this->loadedClasses[$var] = $this->loadClass($var, $this);
		}
		return $this->loadedClasses[$var];
	}
	
	/**
	 * Возвращает ссылку на класс с контентом
	 *
	 * @param String $type
	 * @return A_Content
	 */
	public function Content($type)
	{
		switch (strtolower($type)) {
			case "html":
				return $this->Html;
				break;
		
			case 'plaintext':
				return $this->PlainText;
				break;
				
			case "cover":	
				return $this->Cover;
				break;
			
			case "catalog":
				return $this->Catalog;
				break;
				
			case "gallery":
				return $this->Gallery;
				break;
				
			case "placeholder":
				return $this->Placeholder;
				break;
				
			case 'news':
				return $this->News;
				break;

			case 'bannerlist':
				return $this->BannerList;
				break;
				
			case "catalog":
				return $this->Catalog;
				break;
				
			case 'comments':
				return $this->Comments;
				break;

			case 'rating':
				return $this->Rating;
				break;
			
			case 'formsender':
				return $this->FormSender;
				break;
				
			default:
				throw $this->Utils->PushError('Undefined content type: '.$type,'Системная ошибка. Обратитесь к разработчикам.');
				break;
		}
		//return false;
	}
	
	private function loadClass($className,&$parent)
	{
		$class_path = "{$this->_api_path}$className.inc";
		
		if (!file_exists($class_path)) {
			throw $this->Utils->PushError("Can't find class file $className; Path: $class_path","Не найден файл с классом");
		}
		require_once("$class_path");
		return new $className($this,$parent);
	}
	
	public function setApiPath($path) {
		if (!file_exists($path)) {
			throw $this->Utils->PushError("Directory '$path' does not exsists","Директория указанная в качестве путя к библиотеке не существует");
		}
		if (!is_dir($path)) {
			throw $this->Utils->PushError("Path: '$path' is not dir","Данный путь не является путем к директории");
		}
		
		if (!ereg("/$",$path)) {
			$path .= "/";
		}
		
		$this->_api_path = $path;
		//$this->_api_path = $this->Utils->fixDirPath($this->_api_path);
		return true;
	}
	
	public function getApiPath() {
		return $this->_api_path;
	}
	
}

abstract class A_Content 
{
	/**
	 * Указатель на родительский класс
	 *
	 * @var MF_Main
	 */
	protected $_top;	
	
	public $content_description;
	public $content_name;

	protected 
		$_parent,
		$_cashe_obj = array();
	
	
	public function __construct($top,$parent)
	{
		$this->_top =& $top;
		$this->_parent =& $parent;
		
		unset($this->content_name);
		unset($this->content_description);
	}
	
	
	
	
	
	/**
	 * 
	 *
	 * @param Integer $id
	 * @return A_SingleContent
	 */
	abstract public function getById($id);
	
	/**
	 * 
	 *
	 * @return A_SingleContent
	 */
	abstract public function add();
}

abstract class A_SingleContent
{
	public 
		$_content_id;
		
	/**
	 * Указатель на родительский класс
	 *
	 * @var MF_Main
	 */
	protected $_top;	
	
	protected    
		$_parent,
		$_data;
	
	public function __construct($top,$parent,$id)
	{
		$this->_top =& $top;
		$this->_parent =& $parent;
		$this->_content_id = $id;
		
		$this->loader();
	}
	
	abstract protected function loader();
	
	abstract public function __get($param);
	
	abstract public function __set($param,$value);
	
	public function delete() {
		$this->deleter();
		
		unset($this->_top);
		unset($this->_parent);
		unset($this->_content_id);
		unset($this->_data);
		
	}
	
	abstract protected function deleter();
	
	public function applyXML($xml_obj) {
		return false;
	}
	
}

